package com.ocom.oauth.config;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import static org.springframework.security.config.Customizer.withDefaults;


/**
 * security 安全相关配置类
 *
 */
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


	@Override
	public void configure(WebSecurity web) throws Exception {
		//ignore
		web.ignoring().antMatchers("/phoneLogin","/aiot/login","/xcx/login","/alixcx/login","/LoginPage/**","/health","/hystrix.stream","/actuator/health","/actuator","/","/captcha/**");
	}



	/**
	 * 安全拦截机制
	 */
	@Override
	protected void configure(HttpSecurity httpSecurity) throws Exception {
		httpSecurity
				.authorizeRequests()
				// 放行
				.antMatchers("/auth/**","/oauth/**","/login/**","test/**","/captcha/**")
				.permitAll()
				// 其他请求必须认证通过
				.anyRequest().authenticated()
				.and()
				.cors(withDefaults())
				.csrf().disable();
	}


//	/**
//	 * 配置跨域
//	 * @return
//	 */
//	@Bean
//	CorsConfigurationSource CorsConfigurationSource() {
//		CorsConfiguration configuration = new CorsConfiguration();
//		configuration.addAllowedOrigin("*");	//同源配置，*表示任何请求都视为同源，若需指定ip和端口可以改为如“localhost：8080”，多个以“，”分隔；
//		configuration.addAllowedHeader("*");//header，允许哪些header，本案中使用的是token，此处可将*替换为token；
//		configuration.addAllowedMethod("*");	//允许的请求方法，PSOT、GET等
//		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//		source.registerCorsConfiguration("/**", configuration);
//		return source;
//	}


	/**
	 * token持久化配置
	 */
	// @Bean
	// public TokenStore tokenStore() {
	// // 本地内存存储令牌
	// return new InMemoryTokenStore();
	// }

	/**
	 * 密码加密器
	 */
	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	/**
	 * 认证管理器配置
	 */
	@Bean
	@Override
	protected AuthenticationManager authenticationManager() {
		return authentication -> daoAuthenticationProvider().authenticate(authentication);
	}

	/**
	 * 认证是由 AuthenticationManager 来管理的，但是真正进行认证的是 AuthenticationManager 中定义的 AuthenticationProvider，用于调用userDetailsService进行验证
	 */
	@Bean
	public AuthenticationProvider daoAuthenticationProvider() {
		DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
		daoAuthenticationProvider.setUserDetailsService(userDetailsService());
		daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
		daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
		return daoAuthenticationProvider;
	}

	/**
	 * 用户详情服务
	 */
	@Bean
	@Override
	protected UserDetailsService userDetailsService() {
		// 测试方便采用内存存取方式
//		InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
//		Collection<? extends GrantedAuthority> authorities
//				= AuthorityUtils.createAuthorityList("ROLE_USER");
//		Set<String> permissions = new HashSet<>();
//		permissions.add("sys:user:admin");
//		YoCiUser yoCiUser = new YoCiUser(1L, 1L, permissions, "user_1", passwordEncoder().encode("123456"), true, true, true, true, authorities);
//		userDetailsService.createUser(yoCiUser);
//		// userDetailsService.createUser(User.withUsername("user_1").password(passwordEncoder().encode("123456")).authorities("ROLE_USER").build());
////		userDetailsService.createUser(User.withUsername("user_2").password(passwordEncoder().encode("1234567")).authorities("ROLE_USER").build());
//		return new UserDetailBiz(passwordEncoder());
		return new UserDetailBiz();
	}

	/**
	 * 设置授权码模式的授权码如何存取，暂时采用内存方式
	 */
	@Bean
	public AuthorizationCodeServices authorizationCodeServices() {
		return new InMemoryAuthorizationCodeServices();
	}

	/**
	 * jwt token解析器
	 */
	 @Bean
	 public JwtAccessTokenConverter accessTokenConverter() {

	 JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
	 // 对称密钥，资源服务器使用该密钥来验证
	 converter.setSigningKey("YoCiyy");
	 return converter;
	 }
}
